<template>
  <view class="demo-page">
		<view  ref="container" class="list-box" @scroll.passive="handleScroll" :style="{height: windowHeight + 'px'}">
			<view :style="paddingStyle">
				<view class="box" :class="{'box-title': item.isMin}" v-for="(item, index) in showList" :key="index">
					<view>{{ item.title }} - {{ item.id }}</view>
				</view>
			</view>
		</view>
		<view class="jump-wrap">
			<input v-model="jumpNumber" label="" class="input"/>
			<view @tap="jump()">跳转</view>
		</view>
  </view>
</template>

<script>
import "./index.scss"
export default {
  data() {
    return {
			windowHeight: 0, // 高度
			jumpNumber: 10, // 跳转到第几项
			allList: [], // 所有数据
			titleHeight: 60, // 标题一项的高度
      oneHeight: 150,  // 单条数据一项的高度
      showNum: 10,    // 可见区域最多能展示多少条数据
      startIndex: 0,   // 渲染元素的第一个索引
			curIndex: 0, // 可见区域第一个元素的index
      canScroll: true,  // 可以监听滚动，用于节流
      scrollTop: 0,// 当前滚动高度,再次返回页面时能定位到之前的滚动高度
			titleList: [], // 标题的所有数组
			titleListPos: [], // 标题距离顶部的位置
			scrollTitleNumber: 0, // 距离顶部距离中包含的标题数量
    }
  },
	computed: {
		// 渲染元素最后的index
    endIndex() {
      let end = this.curIndex + this.showNum * 2; // 2倍是需要预留缓冲区域
      let len = this.allList.length
      return end >= len ? len : end;  // 结束元素大于所有元素的长度时，就取元素长度
    },
    // 需要渲染的数据
    showList() {
      return this.allList.slice(this.startIndex, this.endIndex)
    },
    // 空白占位的高度
    paddingStyle() {
			console.log(this.allList.length - this.endIndex, this.scrollTitleNumber)
			let remainTitlesL = this.titleList.length - this.scrollTitleNumber
			let remianItemsLTmp = this.allList.length - this.endIndex - remainTitlesL
			// 剩余普通项的数据
			let remianItemsL = remianItemsLTmp >= 0 ? remianItemsLTmp : 0 
			// 剩余普通项的高度
			let remainItemsHeight = remianItemsL * this.oneHeight
			// 剩余标题项的高度
			let remainTitlesHeight = remianItemsLTmp < 0 ? remainTitlesL * this.titleHeight + remianItemsLTmp * this.titleHeight : remainTitlesL * this.titleHeight
      return {
        paddingTop: this.jumpScrollTop + 'px',
        paddingBottom: (remainItemsHeight +  remainTitlesHeight) + 'px'
      }
    },
		jumpScrollTop() {
			let _scrollTop = this.startIndex * this.oneHeight
			let titleNumber = 0
			for(let i = 0; i < this.titleList.length; i++) {
				if(this.startIndex > this.titleList[i]) {
					titleNumber = i + 1
				}
			}
			this.scrollTitleNumber = titleNumber
			_scrollTop = _scrollTop - (titleNumber * (this.oneHeight - this.titleHeight))
			return _scrollTop
		}
	},
	onLoad() {
		let _this = this
		this.$Hola.getSystemInfo({
			success: function(res) {
				_this.windowHeight = res.windowHeight
				_this.oneHeight = res.windowWidth / 750 * _this.oneHeight
				_this.titleHeight = res.windowWidth / 750 * _this.titleHeight
				let testData = [
					{
						title: '测试头部'
					}
				]
				let item = Object.assign({}, testData[0])
				let i = 0
				let isTiltle = [0, 50, 53, 57, 100, 200, 2999]
				while (i < 3000) {
					let newItem = {...item, id:i, isMin: isTiltle.includes(i) ? true : false}
					_this.allList.push(newItem)
					i++
				}
				_this.titleList = _this.allList.filter(u => u.isMin).map(u => u.id)
				_this.titleListPos = []
				for(let i = 0; i < _this.titleList.length; i++) {
					_this.titleListPos.push((_this.titleList[i] - i) * _this.oneHeight  + i * _this.titleHeight)
				}
			}
		})
	},
  methods: {
		jump() {
			this.startIndex = this.jumpNumber
			this.scrollTop = this.jumpScrollTop
			this.$refs.container.$el.scroll({
				top: this.jumpScrollTop,
				// behavior: 'smooth'
			})
		},
		// canShowNum() {
    //   // ~~ 按位两次取反，得到整数
    //   this.showNum = ~~(this.$refs.container.offsetHeight / this.oneHeight) + 2;
    // },
		// 监听滚动
    handleScroll(e) {
      if (this.canScroll) {
        this.canScroll = false
        // 处理数据
        this.handleData(e)
        // 节流
        let timer = setTimeout(() => {
          this.canScroll = true
          clearTimeout(timer)
          timer = null
        }, 30)
      }
    },
    handleData(e) {
      // 记录当前元素滚动的高度
      this.scrollTop = e.target.scrollTop
			// 计算里面包含了多少个标题
			let titleNumber = 0
			for(let i = 0; i < this.titleListPos.length; i++) {
				if(this.scrollTop > this.titleListPos[i]) {
					titleNumber = i + 1
				}
			}
			this.scrollTitleNumber = titleNumber
      // 可见区域第一个元素的index
      this.curIndex = ~~((this.scrollTop - (titleNumber * this.titleHeight)) / this.oneHeight) + titleNumber
      // 渲染区域第一个元素的index，这里缓冲区域的列表条数使用的是this.showNum
      this.startIndex = this.curIndex < this.showNum ? 0 : this.curIndex - this.showNum
			// console.log(this.curIndex, this.startIndex)
    },
  }
}
</script>
